package dabs.ginterface;

import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import dabs.engine.GameEngine;
import dabs.engine.control.ComponentCommand;
import dabs.engine.control.GameCommand;
import dabs.engine.control.ReadCommand;

// input a string, determine if it's a game command or component command
// general component command: 'component name', 'arg1', 'arg2', ...
// let component deal with the format, for component commands we have (String, ArrayList<String>)
// reading, how to do reading?
// have parser return a different object:
// gamecommand: string
// component command: componentname, arrayList<String> args
// read: componentname, componentproperty



public class CommandParser {

	Pattern gameCommandPattern, componentCommandPattern, readPattern;
	public CommandParser() {
		
		// (?:regex) means a NON-capturing group
		// a name followed by a optional number (eg. valve32)
		String componentNameRegex = "(?:condenser|pump|reactor|valve|turbine)\\d*";
		gameCommandPattern      = Pattern.compile(GameEngine.getCommandRegex());
		
		// 'read' followed by a component name and a (optional) single argument 
		readPattern             = Pattern.compile("read +(\\w+) *(\\w+)?");
		
		// a component followed by any number of arguments (group all of the arguments into a single group)
		componentCommandPattern = Pattern.compile(String.format("(%s) +((?:\\w+ *)+)", componentNameRegex));
	}
	
	public String type(String input) {
		if (gameCommandPattern.matcher(input).matches()) return "gamecommand";
		if (componentCommandPattern.matcher(input).matches()) return "componentcommand";
		if (readPattern.matcher(input).matches()) return "read";
		return "";
	}
	
	public GameCommand asGameCommand(String input) {
		if (!gameCommandPattern.matcher(input).matches()) throw new RuntimeException("Invalid string");
		return new GameCommand(input);
	}
	
	public ComponentCommand asComponentCommand(String input) {
		Matcher m = componentCommandPattern.matcher(input);
		if (!m.matches()) {
			throw new RuntimeException("Invalid String");
		} else {
			ArrayList<String> arguments = new ArrayList<String>();
			for (String str : m.group(2).split(" ")) {
				arguments.add(str.trim());
			}
			return new ComponentCommand(m.group(1), arguments);
		}
	}
	
	public ReadCommand asReadCommand(String input) {
		Matcher m = readPattern.matcher(input);
		if (!m.matches()) {
			throw new RuntimeException("Invalid String");
		} else {
			// if command is 'read compname' then group(2) will be null
			return new ReadCommand(m.group(1), m.group(2) == null ? "" : m.group(2));
		}
	}

}
